Action The arithmetic addition operator yields the sum of the values of expression1 and expression2.
Examples 1 + 1
» 2
UserTalk can add one and one with great facility!
"one" + "one"
» oneone
The addition operator can be used to concatenate strings.
3 + "k bytes needed."
« 3k bytes needed.
Notes UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; the two expressions need not be of the same type to be added together. Generally, the resulting type — which determines the method of addition — is the more complex type, the one that can most readily represent both values.
See Also –
*
/
%
Verb -
Syntax expression1 – expression2
Action The arithmetic subtraction operator yields the difference of the values of expression1 and expression2.
Examples 3 – 0.5
» 2.5
The number 3 is “promoted” to a double, the type of 0.5, in order to perform the subtraction.
"workfile.backup" – ".backup"
» workfile
The subtraction operator works with strings; the result is the removal of the first occurrence of the second string from the first string.
"abc" – "def"
« abc
The second string does not appear in the first, so nothing is removed.
Notes UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; the two expressions need not be of the same type to be subtracted. Generally, the resulting type — which determines the method of subtraction — is the more complex type, the one that can most readily represent both values.
The minus operator can also appear before a single operand to indicate arithmetic negation.
See Also +
*
/
%
Verb *
Syntax expression1 * expression2
Action The arithmetic multiplication operator yields the product of the values of expression1 and expression2.
Examples 3 * 0.5
» 1.5
The number 3 is “promoted” to a double, the type of 0.5, in order to perform the multiplication.
"abc" * "def"
«
This statement generates an error; only numbers can be used as multiplication operands.
Notes UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; the two expressions need not be of the same type to be multiplied together. Generally, the resulting type is the more complex type, the one that can most readily represent both values.
Only numeric-compatible types — short, long, single, double, date, etc. — can be multiplied.
See Also +
–
/
%
Verb /
Syntax expression1 / expression2
Action The arithmetic division operator yields the result of dividing the value of expression1 by the value of expression2.
Examples 10 / 3
» 3
The result of integer division is truncated.
10 / 3.0
» 3.3333
The number 10 is “promoted” to a double, the type of 3.0, in order to perform the division.
long (clock.now () / 3600)
» 770199
This expression yields the number of hours that have passed since midnight, Jan 1, 1904.
Notes UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; the two expressions or the division operation need not be of the same type. Generally, the resulting type is the more complex type, the one that can most readily represent both values.
Only numeric-compatible types — short, long, single, double, date, etc. — can be divided by one another.
See Also +
–
*
%
Verb =
Syntax identifier = expression
Action Evaluates expression and assigns the resulting value to identifier.
Examples local (x);
x = 3 * 4
» 12
The assignment statement causes the value of the expression “3 * 4” to be stored in the local variable “x”.
scratchpad.when = clock.now ()
» 11/11/91; 7:36 PM
In this case the expression “clock.now ()” yielded a date value, which was then assigned to the cell named “when” in the table named “scratchpad.” (The “when” cell need not have already existed.)
Notes The identifier need not specify an existing database cell; the assignment statement will create an item with the given name in the specified table. If no table is specified, a local variable is implicitly declared in the current scope level. That is, an assignment to an undefined identifier behaves as if it were a local declaration. While this can be a timesaver, it is generally bad practice to count on this behavior; as a script becomes more complex, it quickly becomes easy to unintentionally modify a variable in an enclosing scope level.
See Also local
Verb ==
Syntax expression1 == expression2
expression1 equals expression2
Action The equality operator yields the boolean value true if the value of expression1 and the value of expression2 are the same.
Examples file.type ("myFile") equals 'TEXT'
» true
This expression evaluates to true if file.type returns ‘TEXT’ as its result.
27 == "27"
» true
When coerced to be of the same type, the two representations of the number 27 are equal, and the result of the operation is true.
Notes There is no difference between the two forms, == and equals.
UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; the two expressions need not be of the same type for their values to be “equal.”
See Also >
<
>=
<=
≠
Verb ≠
Syntax expression1 ≠ expression2
expression1 != expression2
expression1 notequals expression2
Action The inequality operator yields the boolean value true if the value of expression1 and the value of expression2 are not the same.
Examples file.type ("myFile") ≠ 'TEXT'
» true
This expression evaluates to true if file.type returns anything other than ‘TEXT’ as its result.
"27" notequals 27
» false
When coerced to be of the same type, the two representations of the number 27 are equal, and the result of the operation is false.
Notes There is no difference between the three forms, !=, ≠ and notequals.
UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; if the two expressions are of different types, it does not imply inequality.
The ≠ symbol can be entered at the keyboard with Option–=.
See Also >
<
>=
<=
==
Verb <
Syntax expression1 < expression2
expression1 lessthan expression2
Action This comparison operator yields the boolean value true if the value of expression1 is less (smaller) than the value of expression2.
Examples file.size ("myFile") < 1000000
» true
This expression evaluates to true if the file contains less than one million characters.
"abd" < "azz"
» true
Notes There is no difference between the two forms, < and lessthan.
String comparison is carried out according to the ASCII sequence; this yields alphabetical results, but lowercase characters sort after all uppercase characters. That is, “A” < “Z” < “a” < “z”.
UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; the two expressions need not be of the same type to be compared.
See Also >
>=
<=
==
≠
Verb <=
Syntax expression1 <= expression2
expression1 ≤ expression2
Action This comparison operator yields the boolean value true if the value of expression1 is less (smaller) than or equal to the value of expression2.
Examples file.size ("myFile") <= 1000000
» true
This expression evaluates to true if the file contains one million or fewer characters.
"abc" ≤ "abc"
» true
The result is true, because the two expressions are equal.
Notes There is no difference between the two forms, <= and ≤.
String comparison is done according to the ASCII sequence. This yields alphabetical results. Lowercase characters sort after all uppercase characters, that is, “A” < “Z” < “a” < “z”.
UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; the two expressions need not be of the same type to be compared.
The ≤ symbol can be entered at the keyboard with Option–<
See Also >
>=
<
==
≠
Verb >
Syntax expression1 > expression2
expression1 greaterthan expression2
Action This comparison operator yields the boolean value true if the value of expression1 is greater (larger) than the value of expression2.
Examples file.size ("myFile") > 1000000
» true
This expression evaluates to true if file.size returns a value larger than one million.
"abdc" > "a"
» true
Notes There is no difference between the two forms, < and greaterthan.
String comparison is carried out according to the ASCII sequence; this yields alphabetical results, but lowercase characters sort after all uppercase characters, that is, “A” < “Z” < “a” < “z”.
UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; the two expressions need not be of the same type to be compared.
See Also <
>=
<=
==
≠
Verb >=
Syntax expression1 >= expression2
expression1 ≥ expression2
Action This comparison operator yields the boolean value true if the value of expression1 is greater (larger) than or equal to the value of expression2.
Examples file.size ("myFile") >= 1000000
» true
This expression evaluates to true if file.size returns a value larger than or equal to one million.
"abc" ≥ "abc"
» true
The result is true, because the two expressions are equal.
Notes There is no difference between the two forms, <= and ≤.
String comparison is carried out according to the ASCII sequence. This yields alphabetical results. Lowercase characters sort after all uppercase characters, that is, “A” < “Z” < “a” < “z”.
UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; the two expressions need not be of the same type to be compared.
The ≥ symbol can be entered at the keyboard with Option–>
See Also >
<
<=
==
≠
Verb not
Syntax not expression
!expression
Action The logical negation (boolean “not”) operator, yields the boolean value true if expression evaluates to false, or false if expression evaluates to true.
Examples not file.exists ("myFile")
This expression evaluates to true if the file does not exist; if the file does exist, it evaluates to false.
Notes There is no difference between the two forms, ! and not.
See Also and
or
Verb ()
Syntax identifier (expression1, ..., expressionN)
Action Invokes the script named by identifier, passing the values resulting from expression1 through expressionN as parameters. The number of parameter provided must match the number expected by the script, as defined in its “on” statement script header. The value returned by the script becomes the value of the script call expression.
Examples clock.now ()
» 11/11/91; 7:51 PM
Here we’re calling the built-in verb clock.now; the result of the call is the value returned by the verb. Note that the parenthesis notation must be used to indicate that we are making a call to the verb, even though it takes no parameters.
on addThree (n1, n2, n3){
return (n1 + n2 + n3)};
total = addThree (1, 2, 3)
» 6
This example illustrates the correspondence between the parameter list provided when calling a script with the parameter declaration in the script’s defining “on” statement.
Notes Forgetting to provide an empty pair of parentheses when no parameters are required is a common scripting error — watch for it.
See Also on
Verb ++
Syntax ++identifier
identifier++
Action The increment operator adds the numeric value 1 to identifier. In the first case, where the increment operator appears before identifier, the value of the increment expression is the value of identifier after it is incremented. That is, the increment operation takes place first, and the result is used as the value of the expression. In the second case, where the increment operator appears after identifier, the value of the increment expression is the value of identifier before it is incremented; the increment operation takes place after the expression’s value has been determined.
Examples x = 3; ++x
» 4
Since x is “pre-incremented,” its final value of 4 is the result of the expression.
x = 3; x++
» 3
In this case, x is “post-incremented,” and the result of the expression is its value before 1 is added to it. Its value after the statement is executed is still 4.
Notes Any type that supports addition can be used with the increment operator.
See Also +
––
Verb --
Syntax ––identifier
identifier––
Action The decrement operator subtracts the numeric value 1 from identifier. In the first case, where the decrement operator appears before identifier, the value of the decrement expression is the value of identifier after it is decremented. That is, the decrement operation takes place first, and the result is used as the value of the expression. In the second case, where the decrement operator appears after identifier, the value of the decrement expression is the value of identifier before it is decremented; the decrement operation takes place after the expression’s value has been determined.
Examples x = 3; ––x
» 2
Since x is “pre-decremented,” its final value of 2 is the result of the expression.
x = 3; x––
» 3
In this case, x is “post-decremented,” and the result of the expression is its value before 1 is subtracted from it. Its value after the statement is executed is still 2.
Notes Any type that supports subtraction can be used with the decrement operator.
See Also –
++
Verb and
Syntax expression1 and expression2
expression1 && expression2
Action The logical conjunction (boolean “and”) operator, yields the boolean value true if both expression1 and expression2 evaluate to true, false otherwise.
Examples file.exists ("myFile") and (!file.exists ("myFile"))
» false
This expression always evaluates to false, because it is impossible for both expressions to be true at the same time.
file.exists ("myFile") and (file.type ("myFile") == 'TEXT')
» true
This expression evaluates to true if “myFile” exists and is a text file.
Notes There is no difference between the two forms, && and and.
UserTalk employs “short-circuit” evaluation of boolean expressions. In other words, if expression1 of an and operation evaluates to false, expression2 will not be evaluated, since it can already be determined that the result of the operation will be false. In example #2 above, the call to file.type will never be made if file.exists returns false (i.e., the file doesn’t exist).
See Also or
not
Verb or
Syntax expression1 or expression2
expression1 || expression2
Action The logical disjunction (boolean “or”) operator, yields the boolean value true if either expression1 or expression2 evaluates to true, false otherwise.
Examples file.exists ("myFile") or !file.exists ("myFile")
» true
This expression always evaluates to true, because it is impossible for both expressions to be false at the same time.
file.isFolder ("myFile") or (file.type ("myFile") != 'TEXT')
» true
This expression evaluates to true if “myFile” is a folder, or is not a text file.
Notes There is no difference between the two forms, || and or.
UserTalk employs “short-circuit” evaluation of boolean expressions. That means that if expression1 of an or operation evaluates to true, expression2 will not be evaluated, since it can already be determined that the result of the operation will be true. So in example #2 above, the call to file.type will never be made if file.isFolder returns true.
See Also and
not
Verb .
Syntax identifier1 . identifier2
identifier1 . [expression2]
Action Names an Object Database cell. The value of a “dotted-ID” expression is the value contained in the database cell.
In the first form above, identifier1 refers to a database table, and identifier2 refers to an item in that table. In the second form, expression2 is evaluated, and the result is treated as a string and used to name the table item. In either case, the item itself need not already exist to be valid. In an assignment, for example, the assignment statement itself will create the named entry to store the value.
Examples scratchpad.x = 7
Assigns the numeric value 7 to the item named “x” in the table named “scratchpad.” If “x” already exists, its previous value is replaced; it not, a new value is created.
examples.age
» 46
Yields the value of the database cell named “age” in the “examples” table.
sizeOf (people.[user.initials].notepad)
» 65
This example demonstrates the power of the bracket notation. First, the expression “user.initials” is evaluated. The resulting value is used to name an item in the “people” table, the one belonging to the current user. Finally, the item named “notepad” is referenced in the table specified by “people.[user.initials].” The result indicates that the outline contains 65 headings.
Notes As illustrated in the third example above, a dotted-ID pair can be used as the identifier for the table in another dotted-ID pair. The full database path to an item is a series of dotted-IDs, starting with the root table. (Though, for brevity, the “root” table itself can be — and often is — omitted.)
See Also @
=
Verb @
Syntax @identifier
Action Takes the address of identifier. The address can be used with the dereference operator (^) to refer back to the original object specified by identifier. Addresses provide a way to refer to Object Database cells rather than their contents. A script that takes the address of an object as a parameter can change the contents of that database location, while a script that takes an object’s value as a parameter works only with a copy of that value.
Examples name = "";
if dialog.ask ("What's your name?", @name)
{msg (name)}
The built-in verb dialog.ask takes the address of a string as its second parameter. When passed the address of the local variable “name,” dialog.ask is able to change its value.
saying = "A bird in the hand is worth two in the bush";
string.countWords (saying)
In this case, the built-in verb string.countWords doesn’t need to be able to change the original string; it just wants to work with its value. Therefore, we don’t use the address operator.
Notes Strings that name database cells can be coerced to an address with the address global verb. As a result, the value of address (“system.verbs”) is equal to @system.verbs.
See Also ^
Verb ^
Syntax expression^
Action This operator is referred to as the dereference operator. It evaluates expression and, interpreting the result as the address of an Object Database cell, yields the value of that cell.
Examples local (addr = @examples.age);
x = addr^
» 46
This simple example shows how the dereference operator extracts the value of the address, in this case the address of the “age” cell in the “examples” table.
on triple (addrN)
addrN^ = addrN^ * 3
triple (@examples.age)
Type this script into a script window. In this example, the local script “triple” multiplies by three the value whose address is passed to it.
The example below demonstrates a more straightforward method of accomplishing the same thing, but it is interesting see how the @ and ^ operators work together here.
on triple (n)
return (n * 3)
examples.age = triple (examples.age)
Type this script into a script window:
typeOf (window.frontmost ()^) == tableType
» true
Here, the value returned by window.frontmost — a string — is treated as a database address, and the type of the value at that address is compared to tableType. If the frontmost window contains a table, the result of the expression will be true.
Notes The technique shown in the second example above is generally advisable only when working with large pieces of data that reside in the database, such as binary values, in which case memory overhead may be reduced. Otherwise, the simpler approach of example #3 is preferable.
See Also @
Verb %
Syntax expression1 % expression2
Action The arithmetic modulus operator yields the remainder when dividing the value of expression1 by the value of expression2.
Examples 10 % 4
» 2
Four goes two times into 10, leaving a remainder of two.
10 % 4.0
»
This statement generates an error; the modulus operator does not work on floating point values, since the result of floating point division is not truncated and thus has no remainder.
long (clock.now () % 3600)
» 2566
This expression yields the number of seconds into the current hour we are right now.
Notes Only integral-compatible types — short, long, date, etc. — can be used in the modulus operation.
UserTalk employs automatic type coercion when evaluating arithmetic and comparative operations; the two expressions of the modulus operation need not be of the same type. Generally, the resulting type is the more complex type, the one that can most readily represent both values.
See Also +
–
*
/
Verb break
Syntax break
Action Terminates the innermost for, loop, fileloop, or while statement in which it is contained. Script execution continues at the next statement following the looping construct, skipping any subsequent statements within the current loop body.
Examples fileloop (fName in folderPath)
if file.isLocked (fName)
lockedFileFound = true
break
++numberOfFiles
if lockedFileFound
msg ("Found a locked file.")
This is just a script fragment, so don’t attempt to execute it. A loop like the one above might be used to count the number of files in a folder about to be deleted, so that a confirmation dialog could be presented to the user. However, since a locked file was found, the folder cannot be deleted, and the loop is terminated early.
loop
if not dialog.ask ("What number am I thinking of?", @x)
return (false)
if x == 16396
break
msg ("Try again!")
This is just a script fragment, so don’t attempt to execute it. This loop prompts the user for a number forever, until he or she exhibits astonishing clairvoyance or gets sick of the game. The break statement allows the loop to be terminated if the user gets lucky.
Notes The break statement only terminates the loop that contains it; loops outside of the innermost loop continue to execute as usual.
See Also for
for
fileloop
loop
while
continue
Verb bundle
Syntax bundle
statements
Action Executes statements once.
Examples bundle «set up the object database for a new run
app.clearNetworkApp ()
Frontier.pathstring = file.getPath ()
menu.currentsuite = ""
modes.currentmenu = 0
Type this script into a script window. In this example, a fragment of Frontier’s standard startup script, the bundle statement serves purely as an encapsulation mechanism. The four statements in the bundle are executed exactly as if they appeared in line, outside of the bundle. The bundle statement provides additional structure to the script so that the statements can be expanded and collapsed together, and have a single comment that describes their combined action.
bundle «make sure the user has a notepad outline
local (notepad = @peopletable^.notepad)
if not defined (notepad^)
new (outlineType, notepad)
Type this script into a script window. This example, taken from Frontier’s “user.login” script, illustrates an additional encapsulation property of the bundle statement. By declaring the “notepad” local variable within the bundle, its scope is only over those statements that actually work with it. As in the first example, the bundle statement can be collapsed leaving just its comment visible.
See Also on
local
Verb case
Syntax case expression
expr1
statements1
expr2
statements2
exprN
statementsN
else
statements
Action Evaluates the case expression, and then evaluates expressions 1 through N in succession until one of the resulting values matches that of the case expression. When a matching value is found, the corresponding statements are executed, and the case statement is exited.
The else clause of the case statement is optional. If it is provided, and none of the expressions in the main case body match the case expression, the else statements are executed.
Examples case dialog.yesNoCancel ("Save changes before quitting?")
1
msg ("Your changes are being saved…")
fileMenu.save ()
2
msg ("Your changes are being discarded…")
3
msg ("Ok, we won’t quit")
return (false) «don’t continue process
fileMenu.quit ()
Type this script into a script window. In this example, dialog.yesNoCancel is known to return a result of 1, 2 or 3. The case statement allows the appropriate action to be taken for each response.
case user.initials
"DW"
msg ("Hi Dave!")
"dmb"
msg ("Yo Doug!")
else
msg ("Howdy stranger.")
Type this script into a script window. This example demonstrates the use of the else clause, and also illustrates a feature of the case statement that is unlike most other languages: the case expression, and the body expressions, can work with values of any type.
Notes The body expressions do not have to be simple constants; they may be complex expressions if desired.
Once an expression’s value matches that of the case expression, none of the subsequent expression are evaluated.
See Also if
Verb continue
Syntax continue
Action Skips the remaining statements in the body of the current for, loop, fileloop, or while statement. Script execution continues with the next iteration of the looping construct, after incrementing the counter (in a for statement), executing the loop iteration expression (in a loop statement), or assigning the next file (in a fileloop statement).
Example fileloop (fName in folderPath)
if file.isFolder (fName) «skip folders
continue
if file.isLocked (fName)
...
if file.size (fName) > 20000
...
(This is a script fragment; do not try to execute it in the Quick Script Window.) In this example, the use of the continue statement avoids having to indent the remainder of the loop body under an if statement. Typically, the continue statement will be used when there is more complex logic involved.
See Also for
fileloop
loop
while
break
Verb fileloop
Syntax fileloop (identifier in expression)
statements
Action Evaluates expression as a string, to be interpreted as a file system path to a folder.
For each file in the folder indicated by expression, fileloop does the following:
1. assigns the full path of the file to identifier
2. executes statements
Example fileloop (fName in file.getSystemFolderPath ())
{msg (file.fileFromPath (fName));
clock.waitSixtieths (30)}
Posts the name of each item in the System Folder to the Main Window, pausing a half-second between each one.
Notes If expression does not specify a valid path to an existing folder, the body statements will not be executed, and an error will be generated.
If expression is the empty string, the fileloop will iterate over all mounted disk volumes.
See Also break
continue
Verb for
Syntax for identifier = expression1 to expression2
statements
Action Evaluates expression1 and expression2 as numeric values.
Assigns the result of expression1 to identifier.
As long as the value of identifier is less than or equal to the result of expression2, for ... to does the following: executes statements and adds 1 to the value of identifier.
Examples for i = 1 to sizeOf (root){
msg (nameOf (root [i]));
clock.waitSixtieths (30)}
It posts the name of each item in the root table to the Main Window, pausing a half-second between each one.
for i = 3 to 2
{msg ("This statement will not be executed")}
Notes If the result of expression1 is greater than that of expression2, the loop body will not be executed even once.
The action of the for statement is almost identical to the following loop statement:
However in the for statement, the expressions are always evaluated as numbers, and expression2 is evaluated once before entering the loop, rather than for each iteration. This gives the for statement a substantial performance advantage.
See Also loop
while
break
continue
Verb if
Syntax if expression
statements1
else
statements2
Action Evaluates the if expression. If the result is true, executes statements1.
The else clause of the if statement is optional. If it is provided, and expression evaluates to false, statements2 are executed.
Examples if not file.exists (path)
{file.new (path);
file.setType (path, 'TEXT')}
In this simple form of the if statement, we only want to execute the statements that create a new text file if the file doesn’t already exist. If the call to file.exists returns true, the expression not file.exists (path) will evaluate to false, and the indented statements will not be executed.
if file.isFolder (path){
size = file.bytesInFolder (path)}
else{
size = file.size (path)}
This example demonstrates the use of the else clause, which enables us to take one of two possible courses of action depending on the result of a test — in this case whether we are dealing with a file or a folder.
See Also case
Verb kernel
Syntax kernel (identifier)
Action Invokes a function built into Frontier’s kernel, one that is implemented in the program code rather than in scripts. The parameters to the script enclosing the kernel statement are passed on to the kernel function.
Example on exists (path)
kernel (file.exists)
Calls to the “exists” script invoke the kernel function file.exists with the path parameter provided.
Notes Syntactically, the kernel call must be the only statement in the body of a script.
The kernel statement is intended primarily for creators of Frontier verb scripts (i.e., UserLand Software), and is not generally applicable to script writing. Its purpose is to allow verb scripts whose names match that of their kernel function to be called with no loss of performance.
Verb local
Syntax local
identifier1 [ = expression1]
identifier2 [ = expression2]
...
identifierN [ = expressionN]
or
local (identifier1 [ = expression1], ..., identifierN [ = expressionN])
Action Creates local variables named identifier1 through identifierN, assigning the initial values that are the result of evaluating expressions 1 through N where provided.
Evaluates each expression provided, assigning the result to the corresponding variable as its initial value.
The scope of the variables is limited to the statements following the local statement, in the same block of code. That is, the definition does not persist past the last statement in the current if, while, loop, for, fileloop, on, bundle, case, or else statement body.
Example local (x = 1)
if file.isFolder (path)
local (x)
x = file.byteInFolder (path) « this "x" is private
msg (string.kBytes (x))
else
local (x = file.size (path)) « this "x" is private
msg (string.kBytes (x))
msg (x) « "x" from first line is still 1
(Do not attempt to execute this script outside a script window.) This example, while not recommended programming style, illustrates how the scope of a local variable is limited to the statements following it in the current body of the containing structural statement.
Notes The local statement does not have to appear as the first statement in a block of code. If it appears in the middle of a block, its scope excludes the statements that appear above it.
UserTalk is a “dynamically scoped” language. That means that local variables can be “seen” by scripts called from a statement in the statement block. It is generally bad programming practice to use this language feature, but advanced script writers may find special circumstances where it may simplify an implementation.
See Also =
Verb loop
Syntax loop
statements
or
loop (expression1; expression2; expression3)
statements
Action In its simplest form, where the three loop expressions are not provided, the loop statement executes its body statements repeatedly, forever. Such a loop can be terminated by a break or return statement in its body, or by the user canceling the script.
In its more complex form, the loop statement is executed as follows:
This loop iterates through all open windows, posting a message with their titles in the Main Window.
loop
if mouse.button () « user pressed the mouse
break
msg ("It's" + clock.now () + "you still haven’t clicked the mouse!")
This loops until the user presses the mouse button, while posting a message of impatience.
Notes The complex loop form is most appropriate when the three expressions work together to control the loop iterations, as in the first example above.
expression1 is executed only once; expression3 is executed after is iteration over the loop body.
If expression2 initially evaluates to false, the loop body (and expression3) will not be executed even once.
The action of the complex loop statement is almost identical to the following while statement:
expression1
while expression2
statements
expression3
However, a continue statement in the while body would not cause expression3 to be executed before the next loop iteration, as it does with the loop statement.
For simple counting loops, the for loop construct is simpler and more efficient.
See Also for
while
break
continue
Verb on
Syntax on identifier (idparam1, idparam2, ..., idparamN)
statements
Action Defines a local script named identifier, with parameters idParam1 through idParamN. The body statements are not executed; that occurs only when the script is invoked with a function call, consisting of identifier followed by a list of parameters enclosed in parentheses.
Examples on countWindows ()
return (appleEvent (app.id, 'app1', 'twin'))
Type this script into a script window. This is the script for app.countWindows in Frontier.root. In this case, the local script countWindows takes no parameters, and its body is the single return statement that returns the result of an appleEvent call. Since the entire script consists of a local script definition, running the script will do nothing but define the script; there is no call to countWindows to cause its body statements to be executed. Scripts like these are intended to be called externally, by other scripts. A script that wishes to execute countWindows must name its database cell in a function call, as in numOfWindows = app.countWindows ().
on lockFiles (folder)
local (fName)
fileloop (fName in folder)
file.lock (fName)
lockFiles ("HD80:folder1")
lockFiles ("HD80:folder2")
Type this script into a script window. This example demonstrates the use of a local script to allow a specialized bit of functionality — in this case locking all of the files in a folder — to be reused within a script. The on statement defines the “lockFiles” local script, which takes a single parameter that is expected to be the path of a folder. Below the script definition are two calls to the script, passing two different folders to be operated on.
Notes The number of parameters defined in the on statement is strict; all calls to the script must provide exactly that number. If the script does not take any parameters, an empty parameter list — () — must be provided in both its definition and any calls to it.
The scope of a script defined with the on statement is generally the same as that of local variables, lasting the rest of the program statement block that contains it. However, if the script is the first local script in a program, and its name matches that of the script database cell that contains it, then scripts elsewhere in the database can call it by naming the database cell (and providing the appropriate parameter list).
The on statement’s parameter list defines the local script’s name and the name of each parameter it requires. There is no specification made of what type of values are expected for each parameter, and thus there is no type validity checking when the script is called. If a parameter is provided whose type is inappropriate for a statement in the script body, an error will occur when executing that statement.
If a script is intended to be callable from other scripts, it is important that its name match that of the database cell containing it. If the name does not match, the script will be assumed to be local to the implementation of the database script. The on statement will be executed as a definition, with the expectation that a call to it will appear subsequently in the body of the database script.
See Also bundle
local
return
Verb return
Syntax return (expression)
Action Evaluates expression and exits the current script, with the result of expression being the value of the call that invoked it.
Example on exponentiate (n, power)
local (i, exp = 1)
for i = 1 to power
exp = exp * n
return (exp)
result = exponentiate (10, 3)
Type this script into a script window. In the last line of “exponentiate”, the local variable “exp” is the expression whose value is returned by the script. In the assignment statement below, the call exponentiate (10, 3) evaluates to 1000 — the value of “exp” when it is used in the return statement. Thus, the value 1000 is assigned to “result.”
Notes While the parentheses around the expression being returned are not required, we recommend their use for improved readability. This is a matter of scripting style and has no effect on the statement’s execution.
See Also on
Verb while
Syntax while expression
statements
Action Evaluates expression. As long as it evaluates to true, the loop statements are executed, and expression is re-evaluated.
Examples while scratchpad.x < 0
if not dialog.getInt ("Enter a positive number:", @scratchpad.x)
return (false)
This loop repeats until the user enters a positive value for scratchpad.x or cancels the dialog. Note that the dialog will never be presented if scratchpad.x is already greater than zero.
while window.frontmost () != ""
window.hide (window.frontmost ())
This loop hides all of the open windows, including the Main Window.
Notes If expression initially evaluates to false, the loop body will not be executed even once.